<template>
  <div class="file-uploader panel panel-default">
    <div class="panel-heading">
      <div class="file-summary">
        <label :for="'file'+_uid">
          <span
            class="btn btn-primary"
            href="javascript:;"
            :disabled="loading"
          >{{loading?'上传中...':'添加文件+'}}</span>
          <input
            :key="'input'+count"
            :multiple="multi"
            @change="handleChange"
            type="file"
            :id="'file'+_uid"
            :accept="accept"
          >
        </label>

        <span style="color:#888" v-if="files.length">已选择{{files.length}}个文件</span>
      </div>
    </div>

    <div class="panel-body">
      <ul class="file-list" ref="files">
        <FileItem
          :data-key="f.key"
          :name="f.name"
          :file="f.file"
          :remote="url"
          :index="index"
          v-for="(f,index) in files"
          :key="f.key"
          @drop="dropFile(index)"
          @complete="handleComplete"
        ></FileItem>
      </ul>
    </div>
  </div>
</template>

<script>
import Sortable from "sortablejs";
import FileItem from "./File.vue";

function getKey() {
  return Math.random()
    .toString(36)
    .slice(-8);
}
export default {
  components: { FileItem },
  props: {
    value: {
      type: Array,
      default: () => []
    },
    accept: {
      type: String,
      default: "image/*"
    },
    url: String,
    multi: {
      type: Boolean,
      default: true
    },
    maxCount: {
      type: [Number, String],
      default: 0
    },
    maxSize: {
      type: [Number, String],
      default: 0
    }
  },
  data() {
    return {
      files: [],
      loading: false,
      count: 1
    };
  },
  computed: {
    fileModel() {
      return this.files.map(o => {
        return {
          name: o.name,
          url: o.url,
          data: o.data
        };
      });
    }
  },
  mounted() {
    if (!Array.isArray(this.value)) {
      throw new TypeError("v-model must be an array");
    }

    this.files.push(
      ...this.value.map(o => {
        return Object.freeze({
          file: o.url,
          url: o.url,
          key: getKey(),
          name: o.name || o.url
        });
      })
    );
    this.$nextTick(() => {
      var sortable = Sortable.create(this.$refs.files, {
        onEnd: evt => {
          const { newIndex, oldIndex, item } = evt;
          const fs = [...this.files];
          const old = fs[oldIndex];
          fs[oldIndex] = fs[newIndex];
          fs[newIndex] = old;
          this.files = fs;
          evt.item.classList.remove("active");
        },
        onUnchoose(evt) {
          evt.item.classList.remove("active");
        },
        onChoose(evt) {
          evt.item.classList.add("active");
        }
      });
    });
  },
  methods: {
    handleComplete(evt) {
      const { index, data } = evt;
      this.files[index].data = data;
      this.$nextTick(() => {
        this.$emit("input", this.fileModel);
      });
    },
    handleChange(evt) {
      const { files } = evt.target;
      const fileArr = Array.from(files);

      if (this.maxCount) {
        const left = +this.maxCount - this.files.length;
        if (files.length > left) {
          alert(`最多只能选择${this.maxCount}张图片`);
          return;
        }
      }
      if (this.maxSize) {
        const find = fileArr.find(o => {
          return o.size / 1024 > +this.maxSize;
        });
        if (find) {
          alert(`文件[${find.name}]超出最大尺寸`);
          return;
        }
      }
      this.files.push(
        ...fileArr.map(o => {
          return {
            file: o,
            name: o.name
          };
        })
      );
      this.$emit("change", files);
      this.count++;
    },
    dropFile(index) {
      confirm("是否删除该文件？") && this.files.splice(index, 1);
      this.$emit("input", this.fileModel);
    }
  }
};
</script>